/* --------------------------------------------------------------------	*
 * master_add.c															*
 * 																		*
 * Master program for adding the elements of an array by using PVM		*
 * --------------------------------------------------------------------	*/
#include <stdio.h>
#include <stdlib.h>
#include <pvm3.h>			/* PVM constants and declarations	*/
#include "tags.h"			/* tags for messages				*/
#include "common.h"			/* common constants					*/

int get_slave_no(int*, int);

int main()
{
	int mytid;
    int	slaves[NUM_SLAVES];	/* array to store the task IDs of slaves	*/
	int items[SIZE];		/* data to be processes						*/
	int result, i, sum;
	int results[NUM_SLAVES];	/* results from the slaves				*/

	/* enroll into the PVM system 	*/
	mytid = pvm_mytid();

	/* initialize the array `items'	*/
	for(i = 0; i < SIZE; i++)
		items[i] = i;

	/* spawn the slaves				*/
	result = pvm_spawn("slave_add", (char**)0, PvmTaskDefault,
			           "", NUM_SLAVES, slaves);

	/* check if proper number of slaves are spawned		*/
	if(result != NUM_SLAVES)
	{
		fprintf(stderr, "Error: Cannot spawn slaves.\n");
		pvm_exit();
		exit(EXIT_FAILURE);
	}

	/* distribute the data among the slaves		*/
	for(i = 0; i < NUM_SLAVES; i++)
	{
		pvm_initsend(PvmDataDefault);
		pvm_pkint(items + i*DATA_SIZE, DATA_SIZE, 1);
		pvm_send(slaves[i], MSG_DATA);
	}

	/* receive the results from the slaves		*/
	for(i = 0; i < NUM_SLAVES; i++)
	{
		int bufid, bytes, type, source;
		int slave_no;
		
		/* receive message from any of the slaves		*/
		bufid = pvm_recv(-1, MSG_RESULT);

		/* get information about the message			*/
		pvm_bufinfo(bufid, &bytes, &type, &source);
		
		/* get the slave number that sent the message	*/
		slave_no = get_slave_no(slaves, source);

		/* unpack the results at appropriate position	*/
		pvm_upkint(results + slave_no, 1, 1);
	}

	/* find the final result			*/
	sum = 0;
	for(i = 0; i < NUM_SLAVES; i++)
		sum += results[i];

	printf("The sum is %d\n", sum);

	/* clean up and exit from the PVM system	*/
	pvm_exit();

	exit(EXIT_SUCCESS);
} /* end main() */
		
/* function to return the slave number of a slave given its task ID	*/
int get_slave_no(int* slaves, int task_id)
{
	int i;

	for(i = 0; i < NUM_SLAVES; i++)
		if(slaves[i] == task_id)
			return i;

	return -1;
} /* end get_slave_no()	*/

/* end master_add.c	*/

